using System.Collections.Generic;
using Cysharp.Threading.Tasks;
using Light.Assets.Scripts.EventManager;
using Refresh;
using UnityEngine;
using UnityEngine.UI;

namespace Light
{
    public class QuickSlotBarInfo : RefreshData<QuickSlotBarInfo>
    {
        /// <summary>
        ///     ��һ�����������ڶ���������
        /// </summary>
        public List<(int, AbstractItemSO)> Items;

        public FunctionBarOperationType type;
    }

    public class QuickSlotBarController : BasePanel
    {
        //����ֻ����Pareng�Ľ�����������������ݵĺ�ȥ����Ҫ�Ļ���˵

        //�������õ�Slot����
        [SerializeField] private int slotNum = 6;

        //Item���ݺ����ɵ�GameObject�Ķ�Ӧ
        private readonly (AbstractItemSO, GameObject)[] itemDataToObjectList = new (AbstractItemSO, GameObject)[6];

        //�������٣�������ʹ���ֵ䣬�Ͼ���ϣ�㷨�ܺ�ʱ��
        private readonly List<(string, GameObject)> slotNameToObjectList = new();

        private Transform content; //�����洢����Slot�ĵط�

        private Image curActiveItemSlotImageUI;

        private int curIndex;

        private GameObject ItemInSlotPrefab; //׼��ʵ������ItemԤ�Ƽ�
        private GameObject slotPrefab; //�������ItemͼƬ�Ĳ��

        public int CurIndex
        {
            set
            {
                curIndex = value;
                ChangeActiveItem(value);
            }
            get => curIndex;
        }

        private async void Awake()
        {
            UIManager.Instance.RegisterPanel("QuickSlotBarController", this);

            content = transform.Find("Content").transform;

            ResManager.Instance.LoadAsync<GameObject>("Slot", s => { slotPrefab = s; }, LoadType.AddressAbles);

            ResManager.Instance.LoadAsync<GameObject>("ItemInSlot", s => { ItemInSlotPrefab = s; },
                LoadType.AddressAbles);

            await UniTask.WaitUntil(() => slotPrefab != null);
            await UniTask.WaitUntil(() => ItemInSlotPrefab != null);

            for (var i = 1; i <= slotNum; ++i)
            {
                var go = Instantiate(slotPrefab, content); //ʵ��������

                //����
                var name = "Slot" + i;

                go.GetComponentInChildren<Text>().text = i.ToString(); //���СԲť
                //������ʶ������
                go.name = name;

                //�洢
                slotNameToObjectList.Add((name, go));
            }
        }

        private void Update()
        {
            if (LightInputManager.Instance.main1Press)
                CurIndex = 0;
            else if (LightInputManager.Instance.main2Press)
                CurIndex = 1;
            else if (LightInputManager.Instance.main3Press)
                CurIndex = 2;
            else if (LightInputManager.Instance.main4Press)
                CurIndex = 3;
            else if (LightInputManager.Instance.main5Press)
                CurIndex = 4;
            else if (LightInputManager.Instance.main6Press) CurIndex = 5;
        }

        public override void Init()
        {
            using var evt = QuickSlotPanelInitEvent.Get();

            EventManager.SendEvent(evt);
        }

        public override void ReOpen()
        {
        }

        /// <summary>
        ///     ����һ���¼��������е���
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="data"></param>
        public override void Refresh<T>(T data)
        {
            base.Refresh(data);
            var info = data as QuickSlotBarInfo;
            if (info.type == FunctionBarOperationType.Add || info.type == FunctionBarOperationType.Init)
                ItemAdd(info, info.type);
            else if (info.type == FunctionBarOperationType.Delete) ItemDelete(info);
        }

        private int GetEffectiveIndex()
        {
            var res = 0;
            foreach (var item in itemDataToObjectList)
            {
                if (item == (null, null)) break;

                ++res;
            }

            return res;
        }

        private void ItemAdd(QuickSlotBarInfo info, FunctionBarOperationType type)
        {
            foreach (var item in info.Items)
            {
                var index = item.Item1 - 1;

                if (index == -1) //�����������ݻ�δ����
                {
                    index = GetEffectiveIndex();

                    //���̨��Ϣ˵׼�����
                    using var evt1 = QuickUpdateItemJsonIndexEvent.Get();
                    evt1.index = index + 1; //json�в���0��ʼ
                    evt1.item = item.Item2;
                    EventManager.SendEvent(evt1);
                }

                //��������ѡ�����ʵĶ���ע�⣺�ڴ洢��ʱ��ʹ�õ���1-6��������������Ҫ����-1��Ϊ�ɱ�������ܵ�����
                var parentTransform = slotNameToObjectList[index].Item2.transform;
                var itemInSlot = Instantiate(ItemInSlotPrefab, parentTransform).GetComponent<ItemInSlot>();
                itemInSlot.name = "ItemInSlot"; //�������֣��ں���Ĳ�����Ҫ�õ�
                itemInSlot.Init(this);
                using var evt = ItemInSlotInfo.Get();
                evt.item = item.Item2;
                itemInSlot.Refresh(evt);

                itemDataToObjectList[index] = (item.Item2, itemInSlot.gameObject); //�ڸ�������λ�ý��и�ֵ����
            }
        }

        private void ItemDelete(QuickSlotBarInfo info)
        {
            foreach (var item in info.Items)
                for (var i = 0; i < itemDataToObjectList.Length; i++)
                    if (itemDataToObjectList[i].Item1 == item.Item2)
                    {
                        //���ٶ����Ƴ�����
                        Destroy(itemDataToObjectList[i].Item2);

                        //֪ͨ��̨���¶�Ӧ��json�����е�index
                        using var evt = QuickUpdateItemJsonIndexEvent.Get();
                        evt.index = -1;
                        evt.item = item.Item2;
                        EventManager.SendEvent(evt);

                        itemDataToObjectList[i] = (null, null);
                    }
        }

        /// <summary>
        ///     ��Item�����������ݽ���ʹ��
        /// </summary>
        /// <param name="origin">��������ק�Ķ���</param>
        /// <param name="target">����ק����ͬһ�㼶�Ķ���</param>
        /// <param name="targetParent">��ק����ĸ�����Ĭ��Ϊ�գ�������Ǿʹ�����ק��һ���յ�Slot��</param>
        public void SwitchItemIndex(GameObject origin, GameObject target, GameObject targetParent = null)
        {
            int originIndex = 0, targetIndex = 0;

            //��ɸѡ��origin��indexλ��
            for (var i = 0; i < itemDataToObjectList.Length; i++)
            {
                if (itemDataToObjectList[i].Item2 == origin) originIndex = i;
                //��ȷ�������
                if (targetParent == null)
                    if (itemDataToObjectList[i].Item2 == target)
                        targetIndex = i;
            }

            //��������ɸѡ�Ƚϳ���Ӧ��SlotIndex
            if (targetParent != null)
                for (var i = 0; i < slotNameToObjectList.Count; i++)
                    //ʹ�øù��ܵ�ǰ���������Slot�������Ǻ��ʵ�
                    if (slotNameToObjectList[i].Item2 == targetParent)
                        targetIndex = i;

            //�����ItemData��Ӧ��Ϸ������ֵ�е����ݽ���
            var tempData = itemDataToObjectList[originIndex];
            itemDataToObjectList[originIndex] = itemDataToObjectList[targetIndex];
            itemDataToObjectList[targetIndex] = tempData;
        }

        /// <summary>
        ///     ����InputSystemָ���İ��������õ�ǰ��Ծ��Item
        /// </summary>
        /// <param name="index">�������Ĳ�����Ҫ������array��ֱ��ʹ�õ�</param>
        private void ChangeActiveItem(int index)
        {
            //active����Ǻ�ɫ��unActive����blue
            if (curActiveItemSlotImageUI == null)
                curActiveItemSlotImageUI = curActiveItemSlotImageUI =
                    itemDataToObjectList[index].Item2.transform.parent.GetComponent<Image>();
            else
                curActiveItemSlotImageUI.color = Color.blue;


            curActiveItemSlotImageUI = itemDataToObjectList[index].Item2.transform.parent.GetComponent<Image>();
            curActiveItemSlotImageUI.color = Color.red;


            using var evt = WeaponChangeEvent.Get();

            evt.item = itemDataToObjectList[index].Item1;

            EventManager.SendEvent(evt);
        }
    }
}